package bancoagitar;

import java.util.List;
import java.util.Random;

public class CheckingAccount {

	private String accountNumber;
	private String name;
	private String SSN;
	double balance;
	Random random = new Random();

	protected CheckingAccount(String accountNumber, String name, String SSN,
			double openingBalance) {
		validateAll(name, SSN, openingBalance);
		initializeAccount(accountNumber, name, SSN, openingBalance);
	}

	private void initializeAccount(String accountNumber, String name,
			String SSN, double openingBalance) {
		this.accountNumber = accountNumber;
		this.name = name;
		this.SSN = SSN;
		this.balance = openingBalance;
	}

	private void validateAll(String name, String SSN, double openingBalance) {
		Util.validateName(name);
		Util.validateSSN(SSN);
		if (openingBalance < BancoAgitar.MIN_BALANCE
				|| openingBalance > BancoAgitar.MAX_BALANCE)
			throw new BancoAgitarException("Invalid opening balance:"
					+ openingBalance);
	}

	public void deposit(double depositAmount, int depositType) {
		if (depositAmount <= 1.00)
			throw new BancoAgitarException(
					"Invalid deposit amount.  Minimum deposit is $1.00");
		validateBalance(balance + depositAmount);

		if (depositAmount < 5000.00) {
			balance += depositAmount;
		} else if (depositType == BancoAgitar.CASH_DEPOSIT_TYPE) {
			fillOutFederalFormForLargeCashDeposit();
			balance += depositAmount;
		} else if (depositType == BancoAgitar.TRANSFER_DEPOSIT_TYPE) {
			fundsLockRequest();
			balance += depositAmount;
		} else if (depositType == BancoAgitar.INTEREST_DEPOSIT_TYPE) {
			markInterest();
			balance += depositAmount;
		}

	}

	public void withdraw(double withdrawAmount) {
		if (withdrawAmount <= 1.00)
			throw new BancoAgitarException("Invalid withdraw amount.  Minimum withdraw amount is $1.00");
		validateBalanceBounds(withdrawAmount);
		
		if (withdrawAmount > cashReserves()) {
			// try to borrow money from another branch to cover withdrawal
			double difference = withdrawAmount - cashReserves();
			Branch branchWithFunds = branchWithReserve(difference, getBranches());
			if (branchWithFunds != null) {
				if (branchWithFunds.willLoan(difference)) {
					if (branchWithFunds.transfer(thisBranch())) {						
						balance -= withdrawAmount;
					} else {
						throw new BancoAgitarException("Funds not availale to withdraw "+withdrawAmount);
					}					
				} else {
					// try second branch to cover withdrawal
					branchWithFunds = branchWithReserve(difference, otherBranches(branchWithFunds, getBranches()));				
					if (branchWithFunds != null) {				
						if (branchWithFunds.willLoan(difference)) {
							if (branchWithFunds.transfer(thisBranch())) {						
								balance -= withdrawAmount;
							} else {
								throw new BancoAgitarException("Funds not availale to withdraw "+withdrawAmount);
							}					
						} else {
							throw new BancoAgitarException("Funds not availale to withdraw "+withdrawAmount);
						}						
					} else {
						throw new BancoAgitarException("Funds not available to withdraw: "+withdrawAmount);
					} // end second try 				
				} 
			} else {
				throw new BancoAgitarException("Funds not available to withdraw: "+withdrawAmount);
			}
			// end of trying to borrow
		} else {
			validateBalance(balance - withdrawAmount);
			balance -= withdrawAmount;
		}
	}

	private void validateBalanceBounds(double withdrawAmount) {
		double balance1 = balance - withdrawAmount;
		if (balance1 < BancoAgitar.MIN_BALANCE || balance1 > BancoAgitar.MAX_BALANCE)
			throw new BancoAgitarException("Invalid balance: " + balance1);
	}

	private List<Branch> otherBranches(Branch branchWithFunds,
			List<Branch> branches) {
		// TODO Auto-generated method stub
		return null;
	}

	public void validateBalance(double balance) {
		if (balance < BancoAgitar.MIN_BALANCE
				|| balance > BancoAgitar.MAX_BALANCE)
			throw new BancoAgitarException("Invalid balance: " + balance);
	}

	public String getName() {
		return name;
	}

	public String getSSN() {
		return SSN;
	}

	public double getBalance() {
		return balance;
	}

	public String getAccountNumber() {
		return accountNumber;
	}

	private void fillOutFederalFormForLargeCashDeposit() {
		// TODO Auto-generated method stub

	}

	private boolean fundsLockRequest() {
		if (random.nextInt(2) % 2 == 0)
			return true;
		else
			return false;
	}

	private double cashReserves() {
		return 1000000.00;
	}

	private void markInterest() {
		// TODO Auto-generated method stub

	}

	private Branch thisBranch() {
		return null;
	}

	private Branch branchWithReserve(double difference, List<Branch> branches) {
		return branches.get(0);
	}

	private List<Branch> getBranches() {
		return null;
	}

}
